package OBJ_Loader;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import klient.Klient;
import objects.AnimationState;
import objects.TimeManager;

/**
 *  
 * @author Bartek & Marcin
 * 
 * @description Main Object for Animation. It uses frames which are read from 
 * specific files tree.
 * 
 */
public class AnimatedObject extends Object{
    private ArrayList<Object> aFrames = new ArrayList<>(); //without Mirrors
    private String what_mirror = "";
    private Boolean use_mirror = false;  
    private ArrayList<AnimatedInfo> i = new ArrayList<>();   //użytkownicy tego obiektu
    private Boolean with_return = false;
    private int max_aframes = 0;
    public AnimatedObject(String file_name, float fx, float fy, float fz, String what_mirror){
        super("obj/mobs/"+file_name+"/"+file_name+".obj",fx,fy,fz);
        this.what_mirror = what_mirror;
        this.use_mirror = ((this.what_mirror.equals("Z")||this.what_mirror.equals("X")||this.what_mirror.equals("Y")) ? true:false);
        int counter = 1;
        String file_path;
        while(true){
            file_path = "obj/mobs/"+file_name+"/a/"+file_name+"_"+counter+".obj";
            File f = new File(file_path);
            if(!f.exists()) { break; }
            aFrames.add(new Object(file_path,fx,fy,fz));
            counter++;
        }
        if(counter==1) {Klient.log("Nie znaleziono żadnej animacji dla "+ file_path);}
        this.max_aframes = (this.use_mirror? this.aFrames.size()*2:this.aFrames.size());
        if(!this.use_mirror){
            with_return = true;
        }
    }
    public int registerObject(){
        getI().add(new AnimatedInfo());
        return getI().size()-1;
    }
    @Override
    public void setScale(float s){
        super.setScale(s);
        for(Object aFrame : getaFrames()){
            aFrame.setScale(s);
        }
    }
    @Override
    public void setColor(float R, float G, float B, float A) {
        super.setColor(R, G, B, A);
        for(Object aFrame : getaFrames()){
            aFrame.setColor(R, G, B, A);
        }
    }
    public void setAnimState(int ID,AnimationState state){
        this.i.get(ID).state = state;
    }
    public void setAnimState(int ID,AnimationState state,int interval){
        this.i.get(ID).state = state;
        this.i.get(ID).TimeID = TimeManager.register(interval);
    } 
    public Boolean drawAnimated(int ID){
        Boolean change_frame = false;
        switch(this.getI().get(ID).state){
            case STOP:
                super.draw();
                break;
            case PLAY: 
                if(TimeManager.check(this.i.get(ID).TimeID)){
                        change_frame = true;
                        this.i.get(ID).aframe+=getI().get(ID).value;
                        if(this.getI().get(ID).aframe >= this.getMax_aframes()) 
                        {
                            this.i.get(ID).loop_counter++;
                           if(!this.getWith_return()) this.i.get(ID).aframe = 0;
                           else{
                               this.i.get(ID).value = -1;
                               this.i.get(ID).aframe = this.getMax_aframes()-1;
                           }
                        }  
                        if( this.getI().get(ID).aframe<0){
                            this.i.get(ID).loop_counter++;
                            this.i.get(ID).value = 1;
                               this.i.get(ID).aframe = 1;
                        }
                     
                    }
            case PAUSE:
                if(this.getI().get(ID).aframe< this.getaFrames().size()){
                    this.getaFrames().get(this.getI().get(ID).aframe).setMirrorX(false);
                    this.getaFrames().get(this.getI().get(ID).aframe).draw();
                }
                else{
                    //what mirror! - ale póki co X
                     this.getaFrames().get(this.getI().get(ID).aframe-this.getaFrames().size()).setMirrorX(true);
                    this.getaFrames().get(this.getI().get(ID).aframe-this.getaFrames().size()).draw();
                }
                break;
        }
        return change_frame;
    }
    public AnimatedInfo getA(int ID){
        return this.i.get(ID);
    }
    @Override
    public void addRotateX(float ang) {
        super.addRotateX(ang);
        for(Object aFrame : getaFrames()){
            aFrame.addRotateX(ang);
        }
    }
    @Override
    public void addRotateY(float ang) {
        super.addRotateY(ang);
        for(Object aFrame : getaFrames()){
            aFrame.addRotateY(ang);
        }
    }
    @Override
    public void addRotateZ(float ang) {
        super.addRotateZ(ang);
        for(Object aFrame : getaFrames()){
            aFrame.addRotateZ(ang);
        }
    }
    @Override
    public void addScale(float s) {
        super.addScale(s);
        for(Object aFrame : getaFrames()){
            aFrame.addScale(s);
        }
    }
    @Override
    public void move(float x, float y, float z) {
        super.move(x, y, z);
        for(Object aFrame : getaFrames()){
            aFrame.move(x, y, z);
        }
    }
    @Override
    public void setRotateZ(float ang) {
        super.setRotateZ(ang);
        for(Object aFrame : getaFrames()){
            aFrame.setRotateZ(ang);
        }
    }
    @Override
    public void setRotateY(float ang) {
        super.setRotateY(ang);
        for(Object aFrame : getaFrames()){
            aFrame.setRotateY(ang);
        }
    }
    @Override
    public void setRotateX(float ang) {
        super.setRotateX(ang);
        for(Object aFrame : getaFrames()){
            aFrame.setRotateX(ang);
        }
    }
    @Override
    public void setMirrorX(boolean val) {
        super.setMirrorX(val);
        for(Object aFrame : getaFrames()){
            aFrame.setMirrorX(val);
        }
    }
    @Override
    public void setMirrorY(boolean val) {
        super.setMirrorY(val);
        for(Object aFrame : getaFrames()){
            aFrame.setMirrorY(val);
        }
    }
    @Override
    public void setMirrorZ(boolean val) {
        super.setMirrorZ(val);
        for(Object aFrame : getaFrames()){
            aFrame.setMirrorZ(val);
        }
    }
    @Override
    public void setRotate(float x, float y, float z) {
        super.setRotate(x, y, z);
        for(Object aFrame : getaFrames()){
            aFrame.setRotate(x, y, z);
        }
    }
    /**
     * @return the aFrames
     */
    public ArrayList<Object> getaFrames() {
        return aFrames;
    }
    /**
     * @return the what_mirror
     */
    public String getWhat_mirror() {
        return what_mirror;
    }
    /**
     * @param what_mirror the what_mirror to set
     */
    public void setWhat_mirror(String what_mirror) {
        this.what_mirror = what_mirror;
    }
    /**
     * @return the use_mirror
     */
    public Boolean getUse_mirror() {
        return use_mirror;
    }
    /**
     * @param use_mirror the use_mirror to set
     */
    public void setUse_mirror(Boolean use_mirror) {
        this.use_mirror = use_mirror;
    }
    /**
     * @return the i
     */
    public ArrayList<AnimatedInfo> getI() {
        return i;
    }
    /**
     * @param i the i to set
     */
    public void setI(ArrayList<AnimatedInfo> i) {
        this.i = i;
    }
    /**
     * @return the with_return
     */
    public Boolean getWith_return() {
        return with_return;
    }
    /**
     * @param with_return the with_return to set
     */
    public void setWith_return(Boolean with_return) {
        this.with_return = with_return;
    }
    /**
     * @return the max_aframes
     */
    public int getMax_aframes() {
        return max_aframes;
    }
    /**
     * @param max_aframes the max_aframes to set
     */
    public void setMax_aframes(int max_aframes) {
        this.max_aframes = max_aframes;
    }
    public long getLoopNumber(int ID){
        return this.i.get(ID).loop_counter;
    }
    public void setToLastFrame(int ID){
        this.i.get(ID).aframe = this.max_aframes-1;
    }
}
